package org.ash.socket.nio;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * @Author: Ashin
 * @Date: 2021/1/25
 * @Description: org.ashin.socket.nio
 * @Version: 1.0.0
 */
public class NioSelectorServer {

    public static void main(String[] args) throws Exception {
        ServerSocketChannel serverSocket = ServerSocketChannel.open();
        serverSocket.bind(new InetSocketAddress(8080));

        serverSocket.configureBlocking(false);

        Selector selector = Selector.open();

        serverSocket.register(selector, SelectionKey.OP_ACCEPT);

        while (true) {
            //阻塞
            selector.select();

            //获取事件集合
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            Iterator<SelectionKey> selectionKeyIterator = selectionKeys.iterator();
            while (selectionKeyIterator.hasNext()) {
                SelectionKey selectionKey = selectionKeyIterator.next();

                if (selectionKey.isAcceptable()) {
                    ServerSocketChannel channel = (ServerSocketChannel) selectionKey.channel();
                    SocketChannel accept = channel.accept();
                    //配置读为非阻塞
                    accept.configureBlocking(false);
                    accept.register(selector, SelectionKey.OP_READ);

                    System.out.println("客户端连接成功" + accept);

                } else if (selectionKey.isReadable()) {
                    SocketChannel channel = (SocketChannel) selectionKey.channel();
                    ByteBuffer allocate = ByteBuffer.allocate(1024);
                    int len = channel.read(allocate);
                    if (len > 0) {
                        System.out.println("接收到数据" + new String(allocate.array()));
                    } else if (len == -1) {
                        System.out.println("客户端把连接关闭" + channel);
                        channel.close();
                    }
                }

                //处理完改事件，从selectionKeys集合中删除，防止下次重复处理
                selectionKeyIterator.remove();
            }
        }
    }
}
